#import "FoursquareTipCollection.h"

// Shared instance of the Foursquare tip collection
static FoursquareTipCollection* sharedTipCollection = nil;

//  This Foursquare integration is possible thanks to the Foursquare API by
//  Eric Butler and associates.
//
//  Copyright (C) 2010 Eric Butler <eric@codebutler.com>

/**
 * A FoursquareTipCollection is an object representing a collection
 * of tips in the Foursquare system.
 *
 * Provides the functionality to perform necessary queries on the set of 
 * tips.
 *
 * Code used within this class and the supporting API was written by 
 * Eric Butler and other associates.
 *
 * The supporting API can be found in ./FourSquareAPI folder.
 *
 * @author      Eric Butler
 * @author      James Lin
 * @version     2.2.2 
 * @since       2.2.2
 */
@implementation FoursquareTipCollection

/**
 * Retrieve the shared instance of the Foursquare tip collection.
 *
 * @return  the shared instance of FoursquareTipCollection
 */
+ (FoursquareTipCollection*)sharedTipCollection {
	@synchronized (self) {
		if (sharedTipCollection == nil) {
			sharedTipCollection = [[FoursquareTipCollection alloc] init];
		}
		return sharedTipCollection;
	}
}

/**
 * Allocate the Foursquare tip collection.
 *
 * @return  the newly allocated shared instance of FoursquareTipCollection
 */
+ (id)alloc {
	@synchronized (self) {
		sharedTipCollection = [super alloc];
		return sharedTipCollection;
	}
}

/**
 * Retrieve a copy of the Foursquare tip collection.
 *
 * @return  the shared instance of FoursquareTipCollection
 */
+ (id)copy {
	@synchronized (self) {
		return sharedTipCollection;
	}
}

/**
 * Initialize the Foursquare tip collection.
 *
 * @return  the initialized FoursquareTipCollection
 */
- (id)init {
    if (self = [super init]) {
		tipCollection = [[NSMutableArray array] retain];
    }
    return self;
}

/**
 * Get the number of tips in the collection.
 *
 * @return  the number of tips in the collection
 */
- (NSInteger)size {
	return [tipCollection count];
}

/**
 * Get the list of tips.
 *
 * @return  the list of tips
 */
- (NSArray*)allTips {
	return tipCollection;
}

/**
 * Helper method to store a tip into this collection.
 *
 * @param tip  the dictionary containing the tip information
 */
- (void)storeTip:(NSDictionary*)tip {
	// Get all the attributes
	NSString* identifier = [tip objectForKey:@"id"];
	NSString* text = [tip objectForKey:@"text"];
	NSString* userID = [[tip objectForKey:@"user"] objectForKey:@"id"];
	NSString* userFirstName = [[tip objectForKey:@"user"] objectForKey:@"firstname"];
	NSString* userLastName = [[tip objectForKey:@"user"] objectForKey:@"lastname"];
	NSString* venueID = [[tip objectForKey:@"venue"] objectForKey:@"id"];
	NSString* venueName = [[tip objectForKey:@"venue"] objectForKey:@"name"];
	NSString* latitude = [[tip objectForKey:@"venue"] objectForKey:@"geolat"];
	NSString* longitude = [[tip objectForKey:@"venue"] objectForKey:@"geolong"];
	
	
	// Build the empty venue container and add it to the collection
	FoursquareTip* tempTip = [FoursquareTip alloc];
	[tempTip initWithID:identifier 
				   text:text 
				 userID:userID 
		  userFirstName:userFirstName 
		   userLastName:userLastName 
				venueID:venueID 
			  venueName:venueName
			   latitude:latitude 
			  longitude:longitude];
	
	NSString* userImageURL = [[tip objectForKey:@"user"] objectForKey:@"photo"];
	
	if (userImageURL && [userImageURL length] > 0) {
		tempTip.tipUserImageURL = userImageURL;
	}
	
	[tipCollection addObject:tempTip];
	[tempTip release];
}

/**
 * Retrieve a fresh set of nearby tip data.
 *
 * @param location     the user location
 * @param theDelegate  the delegate handling update notification
 * @param tipLimit     the maximum number of tips to find
 */
- (void)updateWithUserLocation:(CLLocation*)location 
				   andDelegate:(id<FoursquareTipCollectionDelegate>)theDelegate 
					  tipLimit:(NSUInteger)tipLimit {
	if (!location) {
		return;
	}
	
	NSString* lat = [NSString stringWithFormat:@"%f", location.coordinate.latitude];
	NSString* lon = [NSString stringWithFormat:@"%f", location.coordinate.longitude];
	delegate = theDelegate;
	
	[Foursquare tipsNearLatitude:lat 
					   longitude:lon 
						   limit:[NSNumber numberWithInt:tipLimit]
						callback:
	 ^(BOOL success, id response) {
		 if (success) {
			 // Clear the collection first
			 [tipCollection removeAllObjects];
			 
			 // Traverse down to the tips array
			 NSDictionary* tipsDict = [response objectForKey:@"tips"];
			 id groupItem  = [tipsDict objectForKey:@"group"];
			 NSArray* tips;
			 
			 if ([groupItem isKindOfClass:[NSArray class]]) {
				 tips = groupItem;
			 } else {
				 NSDictionary* groupDict = (NSDictionary*)groupItem;
				 tips = [groupDict objectForKey:@"tip"];
			 }
			 
			 // Add each tip to the collection
			 if ([groupItem isKindOfClass:[NSArray class]]) {
				 for (id tipsValue in tips) {
					 NSDictionary* group = (NSDictionary*)tipsValue;
					 if ([[group objectForKey:@"tip"] isKindOfClass:[NSArray class]]) {
						 NSArray* newTips = [group objectForKey:@"tip"];
						 for (id tipValue in newTips) {
							 NSDictionary* tip = (NSDictionary*)tipValue;
							 [self storeTip:tip];
						 }
					 }
				 }
			 } else {			 
				 for (id value in tips) {
					 NSDictionary* tip = (NSDictionary*)value;
					 [self storeTip:tip];
					 //NSLog(@"Tips count: %d", [tipCollection count]);
				 }
			 }
				 [delegate handleTipCollectionUpdateDone];
		 }
	 }];
}

/**
 * Deallocate the shared Foursquare tip collection.
 */
- (void)dealloc {
	delegate = nil;
	[tipCollection release], tipCollection = nil;
	[sharedTipCollection release], sharedTipCollection = nil;
	[super dealloc];
}

@end
